# Python 装饰器
# 装饰器是一种函数，它可以用来修改另一个函数的行为。它接受一个函数作为参数，并返回一个新的函数或修改原来的函数
# 装饰器的语法是 "@decorator"，其中 "@" 称为装饰器语法，decorator 指代被装饰的函数。
# 装饰器的作用是为函数动态添加功能，它可以让函数在不需要修改原函数代码的前提下，增加额外的功能。
# 装饰器的语法和用法非常灵活，可以用来添加功能，修改函数的输入输出，甚至是替换掉函数。
import time


# 装饰器的语法使用 @decorator_name 来应用在函数或方法上。
# Python 还提供了一些内置的装饰器，比如 @staticmethod 和 @classmethod，用于定义静态方法和类方法。

# 装饰器的应用场景：
# 日志记录: 装饰器可用于记录函数的调用信息、参数和返回值。
# 性能分析: 可以使用装饰器来测量函数的执行时间。
# 权限控制: 装饰器可用于限制对某些函数的访问权限。
# 缓存: 装饰器可用于实现函数结果的缓存，以提高性能。


# 定义一个计时装饰器函数
def timer(func):                                # 定义装饰器函数，接收被装饰的函数作为参数
    def wrapper():                              # 定义一个包装函数用来包装扩展功能
        begin_time = time.time()                # 记录开始时间
        func()                                  # 执行被装饰的函数
        end_time = time.time()                  # 记录结束时间
        print("耗时: ", end_time - begin_time)
    return wrapper                              # 这里必须返回包装函数

# 定义一个被装饰的函数
# 使用装饰器来装饰 my_func() 函数
@timer
def my_func():
    print("fuck you")

# 调用 my_func() 函数，这样 my_func() 函数调用时会自动执行timer()函数，并打印函数执行时间
my_func()


# 带参数的装饰器
# 如果原函数需要参数，可以在装饰器的 wrapper 函数中传递参数
def decorator_func(origin_func):
    def wrapper(*args, **kwargs):
        # 定义执行原始函数之前的操作
        print("执行原始函数之前的操作")
        # 执行原始函数
        origin_func(*args, **kwargs)
        # 定义执行原始函数之后的操作
        print("执行原始函数之后的操作")
    return wrapper

# 使用装饰器
@decorator_func
def target_func(arg1, arg2):
    print("目标函数执行结果:", arg1 + arg2)
# 调用目标函数
target_func(1, 2)


# 装饰器本身也可以接收参数
def repeat(num):                             # 定义一个装饰器，接收一个参数 num
    def decorator_func(func):                # 定义一个装饰器函数，接收被装饰的函数作为参数
        def wrapper(*args, **kwargs):        # 定义一个包装函数用来包装扩展功能
            for i in range(num):             # 重复执行 num 次被装饰的函数
                func(*args, **kwargs)
        return wrapper
    return decorator_func

# 使用装饰器并传递参数
@repeat(3)
def print_hello():
    print("fuck")
# 执行目标函数, 输出 "fuck" 三次
print_hello()


# 类装饰器
# 装饰器可以用来修改类的行为，比如添加属性、方法等。
# 类装饰器的语法是 "@decorator"，其中 "@" 称为装饰器语法，decorator 指代被装饰的类。
# 类装饰器的作用是为类动态添加功能，它可以让类在不需要修改原类代码的前提下，增加额外的功能。

# 定义一个类装饰器
# def my_decorator(cls):
#     class Wrapper(cls):
#         def __init__(self, *args, **kwargs):
#             print("执行 __init__ 方法")
#             super().__init__(*args, **kwargs)
#
#         def display(self):
#             print("类方法执行之前的操作")
#             self.wrapped.display()
#             print("类方法执行之后的操作")
#     return Wrapper
#
# # 定义一个被装饰的类
# @my_decorator
# class MyClass:
#     def __init__(self, name):
#         self.name = name
#
#     def display(self):
#         print("hello, ", self.name)
#
# # 实例化 MyClass 类
# obj = MyClass("风清影竹")
# # 调用 display() 方法
# obj.display()


# 内置装饰器
# Python 还提供了一些内置的装饰器，比如 @staticmethod 和 @classmethod，用于定义静态方法和类方法。

# @staticmethod
# 静态方法不需要实例化就可以调用，可以直接通过类名调用。
# 静态方法可以访问类的属性和方法，但不能访问实例属性和方法。
# 静态方法的第一个参数是 cls，表示当前的类。

# @classmethod
# 类方法不需要实例化就可以调用，可以直接通过类名调用。
# 类方法可以访问类的属性和方法，但不能访问实例属性和方法。
# 类方法的第一个参数是 cls，表示当前的类。

# 示例：
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @staticmethod
    def static_method():
        print("静态方法")

    @classmethod
    def class_method(cls):
        print("类方法")

# 实例化 Person 类
p = Person("张三", 20)
print(p.name, p.age)

# 调用静态方法
Person.static_method()
# 调用类方法
Person.class_method()


# 多个装饰器的应用
# 多个装饰器可以组合使用，实现更复杂的功能。
# 多个装饰器的执行顺序是自上而下，即先执行最外层的装饰器，然后再执行里层的装饰器。
# 多个装饰器使用时，被修饰的函数只会被执行一次
# 示例：
@decorator_func
@timer
def my_func():
    print("fuck you")

my_func()